/// 本文件由reazhuang@outlook.com开发编写 *CodeMaid自动格式化*

//////////////////////////////////
///
/// 主要用途：
/// 从展开的选项中选择一项
/// 即设计上只绑定单选
///
//////////////////////////////////
///
/// 绑定布尔：是、否、空，title与value一样，可以通过设置YesText、NoText来更改title值
/// 绑定枚举：枚举值展开、空，title与value一样
/// 绑定ComboSelectList，则将Text绑定为title，Value绑定为title
/// 绑定用户自定义数据列表，则将TextKey绑定为title，ValueKey绑定为value

using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;

namespace ReaWTM.LayuiHelper
{
	[HtmlTargetElement("wt:radio", Attributes = REQUIRED_ATTR_NAME, TagStructure = TagStructure.WithoutEndTag)]
	public class RadioTagHelper : BaseFieldTag
	{
		private Type _modelType;
		public BoolComboTypes BoolType { get; set; } = BoolComboTypes.Custom;
		/// <summary>
		/// 改变选择时触发的js函数，func(obj)格式;
		/// <para>
		/// obj.$el得到radio原始jquery dom对象
		/// </para>
		/// <para>
		/// obj.value被点击的radio的value值,true,false
		/// </para>
		/// </summary>
		public string ChangeFunc { get; set; }

		public ModelExpression Items { get; set; }

		public string NoText { get; set; }
		public string TextKey { get; set; } = "Text";
		public string ValueKey { get; set; } = "Value";
		public string YesText { get; set; }
		public override void Process(TagHelperContext context, TagHelperOutput output)
		{
			_modelType = Field.Metadata.ModelType;
			if (_modelType.IsList())
			{
				throw new Exception("wt:radio不可用于绑定列表");
			}
			SetDefaultEmpty(CoreProgram._localizer["Sys.PleaseSelect"]);
			output.TagName = "input";
			output.TagMode = TagMode.StartTagOnly;
			output.Attributes.Add("type", "hidden");
			output.Attributes.Add("wtm-verify", "这是一个隐藏验证表单");

			StringBuilder builder = new StringBuilder();

			if (_modelType.IsNullable())
			{
				//添加空选项
				builder.Append($@"<input wtm-null id='null{Id}' type='radio' name='{GetName(context)}' title='{EmptyText}' value>");
			}

			builder.Append($@"
<script>
wtm.radio_Render({{
id:'{Id}',
url:'{ItemUrl}',
data:{JsonSerializer.Serialize(GetItems(), JsonOptions2)},
value:'{GetDefaultValue()}',
fieldName:'{GetName(context)}',
textKey:'{TextKey}',
valueKey:'{ValueKey}',
changeFunc:'{ChangeFunc}',
beforeMount:'{BeforeMount}',
mounted:'{Mounted}',
}});
</script>
");

			output.PostElement.AppendHtml(builder.ToString());
			base.Process(context, output);
		}

		protected override void SetName(TagHelperContext context, TagHelperOutput output)
		{
			//验证字段不给name
			return;
		}

		protected override string GetDefaultValue()
		{
			if (Field.Model != null)
			{
				DefaultValue = JsonSerializer.Serialize(Field.Model, JsonOptions2);
			}
			return DefaultValue;
		}

		private List<ComboSelectListItem> GetItems()
		{
			var _modeltype = Field.Metadata.ModelType;
			var listItems = new List<ComboSelectListItem>();

			if (ItemUrl != null)
			{
				return listItems;
			}

			if (Items?.Model == null)
			{
				var checktype = _modeltype;
				if (_modeltype.IsGenericType && typeof(List<>).IsAssignableFrom(_modeltype.GetGenericTypeDefinition()))
				{
					checktype = _modeltype.GetGenericArguments()[0];
				}

				if (checktype.IsEnumOrNullableEnum())
				{
					listItems = checktype.ToListItems(DefaultValue ?? Field.Model);
				}
				else if (checktype == typeof(bool) || checktype == typeof(bool?))
				{
					if (BoolType == BoolComboTypes.Custom)
					{
						listItems = Utils.GetBoolCombo(BoolComboTypes.Custom, null, YesText, NoText);
					}
					else
					{
						listItems = Utils.GetBoolCombo(BoolType);
					}
				}
			}
			else // 添加用户设置的设置源
			{
				if (typeof(IEnumerable<ComboSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
				{
					if (typeof(IEnumerable<TreeSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
					{
						listItems = (Items.Model as IEnumerable<TreeSelectListItem>).FlatTreeSelectList().Cast<ComboSelectListItem>().ToList();
					}
					else
					{
						listItems = (Items.Model as IEnumerable<ComboSelectListItem>).ToList();
					}
				}
			}
			return listItems;
		}
	}
}